-- Script/CharacterMonitor.lua
-- 角色状态监视器（集成动作模式）- 添加翻滚方向功能

local CharacterMonitor = {}
CharacterMonitor.__index = CharacterMonitor

function CharacterMonitor.new(movementSystem, characterId)
    local Unit = require("Script.Unit")
    
    local unitInstance = Unit.create(characterId)
    
    return setmetatable({
        movementSystem = movementSystem,
        characterId = characterId,
        unitInstance = unitInstance,
        
        currentMode = "chi",
        modes = {
            chi = { name = "吃", priority = 1 },
            chui = { name = "锤", priority = 2 },
            zao = { name = "凿", priority = 3 }
        },
        
        _lastInAir = false,
        _lastHealth = unitInstance.currentHealth,
        _actionTimers = {},
        _actionCooldown = 0,
        _lastMoveState = "idle",
        _lastJumpState = "grounded",
        _lastFacingDirection = unitInstance.facingDirection,
        
        _isRolling = false,
        _rollCooldown = 0,
        _rollInvincibleTimer = 0,
        _canRoll = true,
        _rollDirection = 1,  -- 记录翻滚方向
        
        _currentSpineAnimation = "chi/chi-idle"
    }, CharacterMonitor)
end

function CharacterMonitor:update(dt)
    local playerEntity = self.movementSystem:getEntity(self.characterId)
    if not playerEntity then return end
    
    local moveStatus = self.movementSystem:getEntityMoveStatus(self.characterId)
    if not moveStatus then return end
    
    local physicsState = moveStatus.physicsState
    local unit = self.unitInstance
    
    unit.position.x = playerEntity.position.x
    unit.position.y = playerEntity.position.y
    unit.velocity.x = playerEntity.velocity.x
    unit.velocity.y = playerEntity.velocity.y
    
    self:_updateRollState(dt)
    self:_updateMovementState(physicsState, moveStatus)
    self:_updateFacingDirection(physicsState, moveStatus)
    self:_updateJumpState(physicsState)
    self:_updateActionState(dt)
    self:_detectStateChanges()
end

-- 更新翻滚状态
function CharacterMonitor:_updateRollState(dt)
    local unit = self.unitInstance
    
    if self._rollCooldown > 0 then
        self._rollCooldown = math.max(0, self._rollCooldown - dt)
    end
    
    if self._rollInvincibleTimer > 0 then
        self._rollInvincibleTimer = math.max(0, self._rollInvincibleTimer - dt)
        unit.isInvincible = true
    else
        unit.isInvincible = false
    end
    
    if unit.isRolling ~= self._isRolling then
        unit.isRolling = self._isRolling
    end
end

function CharacterMonitor:_updateMovementState(physicsState, moveStatus)
    local unit = self.unitInstance
    
    if self._isRolling then
        unit.currentAction = "roll"
        unit.moveState = "rolling"
        return
    end
    
    local isMoving = physicsState.horizontalSpeed > 10
    if isMoving ~= unit.isMoving then
        unit.isMoving = isMoving
    end
    
    local isSprinting = moveStatus.isSprinting or false
    if isSprinting ~= unit.isSprinting then
        unit.isSprinting = isSprinting
    end
    
    local newMoveState
    if physicsState.isInAir then
        if unit.isGrounded then
            unit.isGrounded = false
        end
        
        if physicsState.verticalSpeed > 0 then
            newMoveState = "jumping"
            unit.currentAction = "jump"
        elseif physicsState.verticalSpeed < 0 then
            newMoveState = "falling"
            unit.currentAction = "fallOff"
        else
            newMoveState = "air_idle"
            unit.currentAction = "fallOff"
        end
    else
        if not unit.isGrounded then
            unit.isGrounded = true
        end
        
        if physicsState.horizontalSpeed < 10 then
            newMoveState = "idle"
            unit.currentAction = "idle"
        elseif physicsState.horizontalSpeed < 400 then
            newMoveState = "walking"
            unit.currentAction = "move"
        elseif physicsState.horizontalSpeed < 200 then
            newMoveState = "running"
            unit.currentAction = "move"
        else
            newMoveState = "sprinting"
            unit.currentAction = "move"
        end
        
        if unit.isSprinting and physicsState.horizontalSpeed > 100 then
            newMoveState = "sprinting"
            unit.currentAction = "move"
        end
    end
    
    if newMoveState ~= self._lastMoveState then
        unit.moveState = newMoveState
        self._lastMoveState = newMoveState
    end
end

function CharacterMonitor:_updateFacingDirection(physicsState, moveStatus)
    local unit = self.unitInstance
    
    local newFacingDirection = unit.facingDirection
    
    if math.abs(physicsState.inputDirection) > 0.1 then
        newFacingDirection = physicsState.inputDirection > 0 and 1 or -1
        if physicsState.inputDirection ~= 0 then
            unit.currentAction = "turn"
        end
    elseif unit.isMoving then
        local velocityX = unit.velocity.x
        if math.abs(velocityX) > 0.1 then
            newFacingDirection = velocityX > 0 and 1 or -1
        end
    end
    
    if newFacingDirection ~= self._lastFacingDirection then
        unit.facingDirection = newFacingDirection
        self._lastFacingDirection = newFacingDirection
    end
end

function CharacterMonitor:_updateJumpState(physicsState)
    local unit = self.unitInstance
    local wasInAir = self._lastInAir or false
    local isInAir = physicsState.isInAir
    
    if not wasInAir and isInAir and physicsState.verticalSpeed > 0 then
        if not unit.isJumping then
            unit.isJumping = true
        end
        if unit.jumpState ~= "jumping" then
            unit.jumpState = "jumping"
            unit.currentAction = "jump"
        end
    end
    
    if wasInAir and not isInAir then
        if unit.isJumping then
            unit.isJumping = false
        end
        if unit.jumpState ~= "grounded" then
            unit.jumpState = "grounded"
            unit.currentAction = "cancel"
        end
    end
    
    if isInAir and physicsState.verticalSpeed < -50 then
        if unit.jumpState ~= "falling" then
            unit.jumpState = "falling"
            unit.currentAction = "fallOff"
        end
    end
    
    self._lastInAir = isInAir
end

function CharacterMonitor:_updateActionState(dt)
    local unit = self.unitInstance
    
    if self._actionCooldown > 0 then
        self._actionCooldown = math.max(0, self._actionCooldown - dt)
        unit.attackCooldown = self._actionCooldown
    else
        if not unit.canAttack then
            unit.canAttack = true
        end
    end
    
    for action, timer in pairs(self._actionTimers) do
        if timer > 0 then
            self._actionTimers[action] = timer - dt
            if self._actionTimers[action] <= 0 then
                self._actionTimers[action] = nil
            end
        end
    end
end

function CharacterMonitor:_detectStateChanges()
    local unit = self.unitInstance
    
    if unit.currentHealth ~= self._lastHealth then
        if unit.currentHealth <= 0 and self._lastHealth > 0 then
            if unit.isAlive then
                unit.isAlive = false
            end
            unit.currentAction = "cancel"
        elseif unit.currentHealth > 0 and self._lastHealth <= 0 then
            if not unit.isAlive then
                unit.isAlive = true
            end
        end
        self._lastHealth = unit.currentHealth
    end
end

-- 开始翻滚
function CharacterMonitor:startRoll()
    if self._rollCooldown > 0 then
        return false
    end
    
    self._isRolling = true
    self._rollInvincibleTimer = 0.15  -- 缩短无敌帧到0.15秒
    self._rollCooldown = 0.1
    
    -- 记录翻滚开始时的方向
    local playerEntity = self.movementSystem:getEntity(self.characterId)
    if playerEntity then
        self._rollDirection = playerEntity.lastDirection or 1
    else
        self._rollDirection = 1
    end
    
    local unit = self.unitInstance
    unit.isRolling = true
    unit.currentAction = "roll"
    unit.moveState = "rolling"
    
    print("角色监视器：开始翻滚，方向: " .. self._rollDirection)
    return true
end

-- 结束翻滚
function CharacterMonitor:endRoll()
    if not self._isRolling then
        return false
    end
    
    self._isRolling = false
    self._rollDirection = 1  -- 重置方向
    
    local unit = self.unitInstance
    unit.isRolling = false
    
    print("角色监视器：结束翻滚")
    return true
end

-- 获取翻滚方向
function CharacterMonitor:getRollDirection()
    return self._rollDirection or 1
end

function CharacterMonitor:switchMode()
    if self._isRolling then
        return self.currentMode, self.modes[self.currentMode]
    end
    
    local modeOrder = {"chi", "chui", "zao"}
    local currentIndex = 1
    
    for i, mode in ipairs(modeOrder) do
        if mode == self.currentMode then
            currentIndex = i
            break
        end
    end
    
    local nextIndex = (currentIndex % #modeOrder) + 1
    local newMode = modeOrder[nextIndex]
    
    self.currentMode = newMode
    
    return newMode, self.modes[newMode]
end

function CharacterMonitor:setMode(modeName)
    if self._isRolling then
        return false
    end
    
    if not self.modes[modeName] then
        return false
    end
    
    self.currentMode = modeName
    return true
end

function CharacterMonitor:getCurrentMode()
    return self.currentMode, self.modes[self.currentMode]
end

function CharacterMonitor:getAvailableModes()
    return self.modes
end

function CharacterMonitor:setAction(action, cooldown)
    if self._isRolling then
        return false
    end
    
    local unit = self.unitInstance
    local Unit = require("Script.Unit")
    
    if not Unit.isActionAvailable(unit, action) then
        return false
    end
    
    if self._actionCooldown > 0 then
        return false
    end
    
    unit.currentAction = action
    if cooldown then
        self._actionCooldown = cooldown
        unit.canAttack = false
        unit.attackCooldown = cooldown
    end
    
    self._actionTimers[action] = 0.1
    
    return true
end

function CharacterMonitor:applyDamage(damage)
    if self._rollInvincibleTimer > 0 then
        return false
    end
    
    local Unit = require("Script.Unit")
    return Unit.applyDamage(self.unitInstance, damage)
end

function CharacterMonitor:heal(amount)
    local Unit = require("Script.Unit")
    return Unit.heal(self.unitInstance, amount)
end

function CharacterMonitor:reset()
    local Unit = require("Script.Unit")
    Unit.reset(self.unitInstance)
    
    self.currentMode = "chi"
    self._lastInAir = false
    self._lastHealth = self.unitInstance.currentHealth
    self._actionTimers = {}
    self._actionCooldown = 0
    self._lastMoveState = "idle"
    self._lastJumpState = "grounded"
    self._lastFacingDirection = self.unitInstance.facingDirection
    
    self._isRolling = false
    self._rollCooldown = 0
    self._rollInvincibleTimer = 0
    self._rollDirection = 1
    self.unitInstance.isRolling = false
    self.unitInstance.isInvincible = false
    
    self._currentSpineAnimation = "chi/chi-idle"
    
    Unit.clearCache()
end

function CharacterMonitor:getState()
    return self.unitInstance
end

function CharacterMonitor:getDefinition()
    return self.unitInstance.definition
end

function CharacterMonitor:isMoving()
    return self.unitInstance.isMoving
end

function CharacterMonitor:isGrounded()
    return self.unitInstance.isGrounded
end

function CharacterMonitor:isSprinting()
    return self.unitInstance.isSprinting
end

function CharacterMonitor:isJumping()
    return self.unitInstance.isJumping
end

function CharacterMonitor:isRolling()
    return self._isRolling or false
end

function CharacterMonitor:isAlive()
    return self.unitInstance.isAlive
end

function CharacterMonitor:isInvincible()
    return self._rollInvincibleTimer > 0
end

function CharacterMonitor:getFacingDirection()
    return self.unitInstance.facingDirection
end

function CharacterMonitor:getPosition()
    return self.unitInstance.position
end

function CharacterMonitor:getCurrentAction()
    return self.unitInstance.currentAction
end

function CharacterMonitor:getCurrentSpineAnimation()
    return self._currentSpineAnimation
end

return CharacterMonitor